package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.common.WarehousePilotService;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.CodeUtil;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.RequestUtils;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.constant.SaleOrderConstants;
import com.alibaba.citrus.ots.common.util.PriceConvertUnit;
import com.alibaba.citrus.ots.common.util.TimeUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.platform_enhance.SaleOrderTag;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.crb2btradecenter.api.orderquery.dto.QuerySingleRequest;
import com.epoch.app.crb2btradecenter.api.orderquery.service.OrderQueryService;
import com.epoch.app.crb2btradecenter.domain.order.model.Order;
import com.epoch.app.crb2btradecenter.messagetask.dto.LoadRequest;
import com.epoch.app.crb2btradecenter.messagetask.model.MessageTask;
import com.epoch.app.crb2btradecenter.messagetask.service.MessageTaskService;
import com.epoch.app.crb2btradecenter.model.dto.TradeMessageSDO;
import com.epoch.app.crb2btradecenter.sdo.OrderLineSDO;
import com.epoch.app.crb2btradecenter.sdo.OrderSDO;
import com.epoch.app.crforecastsales.model.dto.ActivitySDO;
import com.epoch.app.crpricecenter.model.enums.ActivityTypeEnum;
import com.epoch.app.crunifiedinventory.model.dto.QueryCargoZoneByIdRequest;
import com.epoch.app.crunifiedinventory.model.dto.QueryCargoZoneByIdResponse;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.epoch.app.otsapplicationadaptersdk.sap.*;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif014v2.dto.BatchHandlerRequest;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif014v2.dto.DoHandlerRequest;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif014v2.service.MnSapIf014V2Service;
import com.epoch.app.otsapplicationadaptersdk.service.ApiAdapterService;
import com.epoch.app.otsb2btradecenter.enums.OrderStatus;
import com.epoch.app.otsforecastsales.api.forecastorderquery.service.ForecastOrderQueryService;
import com.epoch.app.otsforecastsales.domian.forecastorder.dto.ForecastOrderLoadListRequest;
import com.epoch.app.otsforecastsales.domian.forecastorder.dto.LoadListResponse;
import com.epoch.app.otsforecastsales.domian.forecastorder.model.ForecastOrder;
import com.epoch.app.otsforecastsales.domian.forecastorder.service.ForecastOrderService;
import com.epoch.app.otsforecastsales.domian.forecastorderline.model.ForecastOrderLine;
import com.epoch.app.otsforecastsales.domian.forecastorderline.service.ForecastOrderLineService;
import com.epoch.app.otsforecastsales.dto.request.QueryForecastOrderDetailRequest;
import com.epoch.app.otsforecastsales.dto.response.QueryForecastOrderDetailReponse;
import com.epoch.app.otsforecastsales.model.dto.PageQueryForecastRequest;
import com.epoch.app.otsforecastsales.otsforecastorderquery.service.OtsForecastOrderQueryService;
import com.epoch.app.otsforecastsales.sdo.ForecastOrderLineSDO;
import com.epoch.app.otsforecastsales.sdo.ForecastOrderSDO;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhoubc
 * @description: 平台请求sap销售订单分公司创建
 * B-b销售订单换货订单同步SAP-创建
 * @date 2021/9/28 21:21
 */
@Component
@Primary
public class MnSapIf014V2ServiceImpl implements MnSapIf014V2Service {
    private final Log log = Log.getLogger(MnSapIf014V2ServiceImpl.class);

    @Autowired
    private BaseDataService baseDataService;
    @Resource
    private CrUnifiedInventoryService crUnifiedInventoryService;
    @Resource
    private ApiAdapterService apiAdapterService;
    @Resource
    private MessageTaskService messageTaskService;
    @Resource
    private OrderQueryService orderQueryService;
    @Resource
    private EpochCacheService epochCacheService;
    @Resource
    private OtsForecastOrderQueryService otsForecastOrderQueryService;

    @Resource
    private ForecastOrderService forecastOrderService;

    @Resource
    private ForecastOrderLineService forecastOrderLineService;

    //换货订单换货行标记
    private static final String EXCHANGE = "exchange";
    private static final String RETURN = "return";


    @Override
    @ProcessInvoker(remark = "MnSapIf014V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public Object doHandler(DoHandlerRequest doHandlerRequest) {
        log.info("MnSapIf014V2ServiceDoHandlerRequest doHandlerRequest:" + JSONObject.toJSONString(doHandlerRequest));
        if (Objects.isNull(doHandlerRequest) || Objects.isNull(doHandlerRequest.getMessage())) {
            log.error("参数为空，直接返回！入参={}", doHandlerRequest);
            return false;
        }

        log.info("message:  " + doHandlerRequest.getMessage());
        TradeMessageSDO tradeMessageSDO = JSON.parseObject(doHandlerRequest.getMessage(), TradeMessageSDO.class);
        log.info("tradeMessageSDO参数:{}",JSON.toJSONString(tradeMessageSDO));
        OrderSDO orderSDO = tradeMessageSDO.getOrderSDO();
        if (Objects.isNull(orderSDO)) {
            log.error("orderSDO为空，orderSDO = {}", orderSDO);
            return false;
        }
        if (CollectionUtils.isEmpty(orderSDO.getOrderLineSDOS())) {
            log.error("orderSDO.getOrderLineSDOS 为空，orderSDO = {}", orderSDO);
            return false;
        }
        if ("ZRE3".equals(orderSDO.getOrderType())) {
            return true;
        }

        MnSapIf014Request request = getMnSapIf014Request(orderSDO);
        log.info("订单同步sap入参： request = {} ", request);
        return apiAdapterService.reqSapSalesOrderCompanyCreate(request);
    }


    @ProcessInvoker(remark = "MnSapIf012V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    private Object sap012CreateFBSaleOrder(List<OrderSDO> orderSDOList) {
        if (CollectionUtils.isEmpty(orderSDOList)) {
            return null;
        }
        log.info("MnSapIf012ServiceImpl sap012CreateFBSaleOrder request:{}",JSON.toJSONString(orderSDOList));
        MnSapIf012Request request = new MnSapIf012Request();
        request.setMessageHeader(RequestUtils.generateMessageHeader("MnSapIf012","ECC"));
        List<MnSapIf012SDO> mnSapIf012SDOList = orderSDOList.stream().map(order -> generateSapIf012SDO(order)).collect(Collectors.toList());
        request.setData(mnSapIf012SDOList);
        log.info("apiAdapterService reqSapSalesOrderCreate request:{}", JSON.toJSONString(request));
        Object executeResult = apiAdapterService.reqSapSalesOrderCreate(request);
        log.info("MnSapIf012ServiceImpl sap012CreateFBSaleOrder result:{}", JSON.toJSONString(executeResult));
        tag(orderSDOList.get(0),mnSapIf012SDOList.get(0).getAllocateOrderId());
        return executeResult;
    }
    private void tag(OrderSDO orderSDO,String allocateOrderId){
        try{
            //针对F-B销售订单做013回来的第一次标记
            String[] orderType = {"ZFOC","ZOR","ZOR8"};
            List<String> orderTypeList = Arrays.asList(orderType);
            if("200".equals(orderSDO.getOrderCategoryCode())  && orderTypeList.contains(orderSDO.getOrderType())){
                String redisKey = String.format("%s-%s", "confirmQuantitySyncFirstTime", allocateOrderId);
                //第一次请求，打一个标记
                boolean setnx = epochCacheService.setnx(BcOtsConstants.REDIS_CACHE_CODE(), redisKey, "1");
                log.info("MnSapIf012ServiceImpl tag setnx={}",setnx);
                if(setnx){
                    epochCacheService.expire(BcOtsConstants.REDIS_CACHE_CODE(), redisKey,30, TimeUnit.MINUTES);
                }
            }
        }catch (Exception e ){
            log.error("MnSapIf012ServiceImpl tag error",e);
        }

    }
    /**
     * 组装创建sap F-B销售订单参数
     * @param orderSDO
     * @return
     */
    private MnSapIf012SDO generateSapIf012SDO(OrderSDO orderSDO) {
        log.info("generateSapIf012SDO param:{}", JSON.toJSONString(orderSDO));
        MnSapIf012SDO sdo = new MnSapIf012SDO();
        sdo.setAllocateOrderId(CodeUtil.convertSapTradeOrderId(orderSDO.getId()));
        //todo bz, orderType与sap是完全对应上、不用转换？
        sdo.setOrderType(orderSDO.getOrderType());
        //平台销售组织->sap
        BaselineGetOrganizationByIdsRequest organizationByIdsRequest = new BaselineGetOrganizationByIdsRequest();
        List<String> saleIds = new ArrayList<>();
        saleIds.add(orderSDO.getOrganizationCode());
//        saleIds.add(orderSDO.getDepartmentCode());
//        saleIds.add(orderSDO.getSaleChannelCode());
        organizationByIdsRequest.setIds(saleIds);
        Map saleMap = (Map) baseDataService.baselineGetOrganizationByIds(organizationByIdsRequest);
        JSONArray result = JSONObject.parseObject(JSONObject.toJSONString(saleMap)).getJSONArray("result");
        if (CollectionUtils.isNotEmpty(result)) {
            for (int i = 0; i < result.size(); i++) {
                JSONObject organizationSDO = result.getJSONObject(i).getJSONObject("organizationSDO");
                String orgId = organizationSDO.getString("id");
                if (orgId.equals(orderSDO.getOrganizationCode())) {
                    sdo.setSaleOrganizationCode(organizationSDO.getString("outCode"));
                }
            }
        }else{
            sdo.setSaleOrganizationCode(orderSDO.getOrganizationOutCode());
        }
        //平台渠道->sap
        BaselineQueryChannelByPageRequest channelByPageRequest = new BaselineQueryChannelByPageRequest();
        channelByPageRequest.setChannelCode(orderSDO.getChannelCode());
        Map map = (Map) baseDataService.baselineQueryChannelByPage(channelByPageRequest);
        JSONObject jsonMap = JSONObject.parseObject(JSONObject.toJSONString(map));
        JSONArray jsonArray = jsonMap.getJSONObject("result").getJSONArray("content");
        if (CollectionUtils.isNotEmpty(jsonArray)) {
            JSONObject jsonObject1 = jsonArray.getJSONObject(0);
            sdo.setSapChannel(jsonObject1.getString("outCode"));
        }
        sdo.setProductGroupCode(orderSDO.getProductGroupCode());
        sdo.setOutCreator(orderSDO.getCreatorName());
        if (orderSDO.getGmtCreate() != null) {
            sdo.setOutCreateDate(DateFormatUtils.format(orderSDO.getGmtCreate(), "yyyy-MM-dd HH:mm:ss"));
            //todo bz, 014接口doctime这么传，确认是否012也这么传 取validTime字段
            sdo.setDocTime(DateFormatUtils.format(orderSDO.getGmtCreate(), "yyyy-MM-dd"));
        }
        //售达方
        sdo.setSoldPartCode(orderSDO.getCustomerCode());
        //送达方
        sdo.setDeliveryPartCode(orderSDO.getReceiveAddressCode());

        if (orderSDO.getCustomerExpectDate() != null) {
            sdo.setExpectedDeliveryTime(DateFormatUtils.format(orderSDO.getCustomerExpectDate(), "yyyy-MM-dd"));
        }
        //装运条件
        sdo.setShipType(orderSDO.getTransportModeCode());
        sdo.setRemark(orderSDO.getRemark());
        sdo.setCostCenter(orderSDO.getCostCenter());
        sdo.setOrderReason(orderSDO.getCreateReason());
        // 创建人工号
        sdo.setExt1(orderSDO.getCreatorCode());
        SearchScItemByDBWhenDegradedRequest scItemByPageRequest = new SearchScItemByDBWhenDegradedRequest();
        List<String> scItemIds = orderSDO.getOrderLineSDOS().stream().filter(line -> null != line.getScItemSDO() && StringUtils.isNotEmpty(line.getScItemSDO().getScItemId())).map(lineSDO -> lineSDO.getScItemSDO().getScItemId()).collect(Collectors.toList());
        List<ScItemSDO> scItemSDOList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(scItemIds)) {
            Map searchReqDTO = new HashMap();
            searchReqDTO.put("scItemIds", scItemIds);
            scItemByPageRequest.setSearchReqDTO(searchReqDTO);
            Result<List<ScItemSDO>> scItemResult = baseDataService.searchScItemByDBWhenDegraded(scItemByPageRequest);
            if (scItemResult != null && CollectionUtils.isNotEmpty(scItemResult.getResult())) {
                scItemSDOList = scItemResult.getResult();
            }
        }
        // 中台预报单行号：SAP预报单行号
        Map<String, String> forecastOrderLineMap = new HashMap<>();
        // SAP预报单号
        String sapForecastOrderNo = null;
        try {
            if (StringUtils.isNotBlank(orderSDO.getSourceOrderNo())) {
                ForecastOrderLoadListRequest loadListRequest = new ForecastOrderLoadListRequest();
                loadListRequest.setOrderBizId(orderSDO.getSourceOrderNo());
                log.info("generateSapIf012SDO#getForecastOrder loadMainOrder request={}", JSON.toJSONString(loadListRequest));
                LoadListResponse mainOrderResponse = forecastOrderService.loadList(loadListRequest);
                log.info("generateSapIf012SDO#getForecastOrder loadMainOrder result={}", JSON.toJSONString(mainOrderResponse));
                if (mainOrderResponse != null && CollectionUtils.isNotEmpty(mainOrderResponse.getResult())) {
                    ForecastOrder forecastOrder = JSON.parseObject(JSON.toJSONString(mainOrderResponse.getResult().get(0)), ForecastOrder.class);
                    sapForecastOrderNo = forecastOrder.getOuterOrderId();
                    ForecastOrderLine orderLineRequest = new ForecastOrderLine();
                    orderLineRequest.setMainOrderBizId(forecastOrder.getOrderBizId());
                    log.info("generateSapIf012SDO#getForecastOrder loadLineList request={}", JSON.toJSONString(orderLineRequest));
                    com.epoch.app.otsforecastsales.domian.forecastorderline.dto.LoadListResponse lineListResponse
                        = forecastOrderLineService.loadList(orderLineRequest);
                    log.info("generateSapIf012SDO#getForecastOrder loadLineList result={}", JSON.toJSONString(lineListResponse));
                    if (lineListResponse != null && CollectionUtils.isNotEmpty(lineListResponse.getResult())){
                        for (Object o : lineListResponse.getResult()) {
                            ForecastOrderLine forecastOrderLine = JSON.parseObject(JSON.toJSONString(o), ForecastOrderLine.class);
                            forecastOrderLineMap.put(forecastOrderLine.getSerialNumber(),forecastOrderLine.getOuterLineId());
                        }
                        log.info("generateSapIf012SDO#getForecastOrder sapForecastOrderNo={} forecastOrderLineMap={}",
                            sapForecastOrderNo, JSON.toJSONString(forecastOrderLineMap));
                    }
                }
            }
        } catch (Exception e) {
            log.error("generateSapIf012SDO#queryForecastOrder error", e);
        }
        List<MnSapIf012Detail> mnSapIf012DetailList = new ArrayList<>();
        Map<String, String> scItemSDOMap = scItemSDOList.stream().collect(Collectors.toMap(ScItemSDO::getScItemId, ScItemSDO::getOuterId, (k1, k2) -> k2));
        String factoryCode = null;
        String stockCode = null;
        for (OrderLineSDO orderLineSDO : orderSDO.getOrderLineSDOS()) {
            if (OrderStatus.CANCELLED.getCode().equals(orderLineSDO.getStatus())) {
                continue;
            }
            MnSapIf012Detail detail = new MnSapIf012Detail();
            //订单平台销售行号
            detail.setAllocateOrderLineId(orderLineSDO.getSerialNumber());
            //子单备注
            detail.setRemarks(orderLineSDO.getRemark());

            if (null != orderLineSDO.getScItemSDO()) {
                if (scItemSDOMap.containsKey(orderLineSDO.getScItemSDO().getScItemId())) {
                    detail.setScItemId(scItemSDOMap.get(orderLineSDO.getScItemSDO().getScItemId()));
                }
                if (null != orderLineSDO.getScItemSDO().getQuantity()) {
                    detail.setQuantity(orderLineSDO.getScItemSDO().getQuantity().toString());
                }
                //  销售单位先硬编码 之后再改
                detail.setUnit(orderLineSDO.getScItemSDO().getSaleUnit());
                try {
                    detail.setProduceDate(TimeUtil.formatYYYY_MM_dd(orderLineSDO.getScItemSDO().getProductationTime()));
                } catch (Exception e) {
                    log.error("sap 012 v2 parse dom date error,",e);
                }
            }
            // ext字段放交货工厂编码
            factoryCode = orderLineSDO.getDeliveryFactoryCode();
            stockCode = orderLineSDO.getStockCode();
            // bz MnSapIf012Detail新增了两个扩展字段ext、ext1用于传递工厂编码+库存地点
//            detail.set
            // //发票 发票行号获取  退货订单才有发票、行号，需找到退货订单对应的正向订单，再找到正向订单的发货单，再找到发票及行号，todo invoiceNo、invoiceLineNo
            // invoiceNo、invoiceLineNo

            //预计交货日期
            try {
                detail.setDeliveryDate(TimeUtil.formatYYYY_MM_dd(orderSDO.getCustomerExpectDate()));
            } catch (Exception e) {
                log.error("sap 012 v2 parse dom date error,",e);
            }

            //ext2 价格，

            //ext3 ext4，查对应预报单，如果能查到，则取对应sap预报单号、sap预报单行号,根据xx字段去查预报单
            if (StringUtils.isNotBlank(sapForecastOrderNo)) {
                detail.setExt3(sapForecastOrderNo);
            }
            if (StringUtils.isNotBlank(forecastOrderLineMap.get(orderLineSDO.getSourceLineNum()))) {
                detail.setExt4(forecastOrderLineMap.get(orderLineSDO.getSourceLineNum()));
            }
            mnSapIf012DetailList.add(detail);

        }
        sdo.setItems(mnSapIf012DetailList);
        //todo bz, 传给sap的工厂编码和库存地点尽量放子单上
        sdo.setDeliveryFactoryCode(factoryCode);
        if("DEFAULT".equals(stockCode)){
            sdo.setDeliveryInventoryCode(null);
        }else{
            sdo.setDeliveryInventoryCode(stockCode);
        }
        log.info("generateSapIf012SDO result:{}", JSON.toJSONString(sdo));
        return sdo;
    }


    @Override
    @ProcessInvoker(remark = "MnSapIf014V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public Object batchHandler(BatchHandlerRequest batchHandlerRequest) {
        log.info("MnSapIf014V2ServiceBatchHandlerRequest doHandlerRequest:" + JSONObject.toJSONString(batchHandlerRequest));
        if (Objects.isNull(batchHandlerRequest) || Objects.isNull(batchHandlerRequest.getMessage())) {
            log.error("批量创单参数为空，直接返回！入参={}", batchHandlerRequest);
            return false;
        }

        log.info("batch message:  " + batchHandlerRequest.getMessage());
        List<MnSapIf014Request> requestList = new ArrayList<>();
        List<MnSapIf014SDO> collect014SDOS = new ArrayList<>();
        String batchNo = batchHandlerRequest.getMessage();
        LoadRequest loadRequest = new LoadRequest();
        loadRequest.setBatchNo(batchNo);
        MessageTask messageTask = messageTaskService.load(loadRequest);
        List<OrderSDO> unifiedInventoryBbOrder = new ArrayList<>();
        List<OrderSDO> unifiedInventoryFBOrder = new ArrayList<>();
        if (Objects.nonNull(messageTask)) {
            Map<String, Object> extraContentMap = JSONObject.parseObject(messageTask.getExtraContent(), Map.class);
            if (MapUtils.isNotEmpty(extraContentMap)) {
                for (String mainOrderId : extraContentMap.keySet()) {
                    QuerySingleRequest orderQueryRequest = new QuerySingleRequest();
                    orderQueryRequest.setMainOrderId(mainOrderId);
                    OrderSDO orderSDO = orderQueryService.querySingle(orderQueryRequest);
                    if (Objects.isNull(orderSDO)) {
                        log.error("orderSDO为空，mainOrderId = {}", mainOrderId);
                        return false;
                    }
                    if (CollectionUtils.isEmpty(orderSDO.getOrderLineSDOS())) {
                        log.error("orderSDO.getOrderLineSDOS 为空，orderSDO = {}", orderSDO);
                        return false;
                    }
                    if ("ZRE3".equals(orderSDO.getOrderType())) {
                        continue;
                    }
                    log.info(" MnSapIf014V2Service batchHandler ordersdo:{}", JSON.toJSONString(orderSDO));
                    String logicWarehouseCode = orderSDO.getFeatures().get("logicWarehouseCode");
                    if (Objects.isNull(logicWarehouseCode)) {
                        // 兼容通过预报单生成销售订单的场景
                        logicWarehouseCode = orderSDO.getWareHouseOutCode();
                    }
//                    boolean isPilot = warehousePilotService.isInPilotScope(logicWarehouseCode);
                    // B-b订单类型 ZBV - 销售公司销售订单 ZFD2 - 销售公司免费订单 ZOR2 - 销售公司常规订单 ZORO - 电商标准销售订单 ZORA - 电商自动销售订单 ZFD3 - 销售公司补货订单

                    String[] businessOrderTypes = {"ZBV","ZFD2","ZOR2","ZORO","ZORA","ZFD3","ZCH2","ZRE2","ZRE3","ZRE5"};
                    //F-B订单类型，ZFOC - 免费销售订单 ZOR - 标准订单 ZOR8 - 直发订单
                    String[] groupOrderTypes = {"ZFOC","ZOR","ZOR8","ZRE","ZREF"};
                    List<String> businessList = Arrays.asList(businessOrderTypes);
                    List<String> groupList = Arrays.asList(groupOrderTypes);
                    if (groupList.contains(orderSDO.getOrderType())) {
                        unifiedInventoryFBOrder.add(orderSDO);
                    } else if(businessList.contains(orderSDO.getOrderType())){
                        log.info("old route ");
                        MnSapIf014Request request = getMnSapIf014Request(orderSDO);
                        requestList.add(request);
                    }else{
                        log.error("order type {} not support",orderSDO.getOrderType());
                    }
                }
            }
        }

        log.info("MnSapIf014V2ServiceImpl#batchHandler requestList={}", JSONObject.toJSONString(requestList));
        log.info("MnSapIf014V2ServiceImpl#batchHandler unifiedInventoryFBOrder={}", JSONObject.toJSONString(unifiedInventoryFBOrder));
        if (CollectionUtils.isNotEmpty(unifiedInventoryFBOrder)) {
            log.info("014 inner call 012");
            Object sap012Result = sap012CreateFBSaleOrder(unifiedInventoryFBOrder);
            log.info("sap012CreateFBSaleOrder  finished");
            messageTask.setStatus(2);
            Integer extraCount = messageTask.getExtraCount();
            int successCount = unifiedInventoryFBOrder.size();
            if (extraCount!= successCount){
                log.error("batch create order to sap ,count not equal,batch no:{}",batchNo);
                messageTask.setStatus(4);
            }
            messageTask.setResultCount(successCount);
            messageTask.setResultContent(JSON.toJSONString(sap012Result));
            messageTaskService.update(messageTask);
            //流程结束
            log.info("sap012CreateFBSaleOrder update message task finished");
            return sap012Result;
        }
        if (CollectionUtils.isEmpty(requestList)) {
            return false;
        }
        MnSapIf014Request firstMnSapIf014Request = requestList.get(0);
        for (MnSapIf014Request mnSapIf014Request : requestList) {
            List<MnSapIf014SDO> mnSapIf014SDOData = mnSapIf014Request.getData();
            collect014SDOS.addAll(mnSapIf014SDOData);
        }
        Integer extraCount = messageTask.getExtraCount();
        int successCount = collect014SDOS.size();

        firstMnSapIf014Request.setData(collect014SDOS);
        log.info("订单批量同步sap入参 requestList = {},firstMnSapIf014Request = {}", requestList,firstMnSapIf014Request);
        Object sapCreateResp = apiAdapterService.reqSapSalesOrderCompanyCreate(firstMnSapIf014Request);
        messageTask.setStatus(2);
        if (extraCount!= successCount){
            log.error("batch create order to sap ,count not equal,batch no:{}",batchNo);
            messageTask.setStatus(4);
        }
        messageTask.setResultCount(successCount);
        messageTask.setResultContent(JSON.toJSONString(sapCreateResp));

        messageTaskService.update(messageTask);
        return sapCreateResp;
    }

    @NotNull
    private MnSapIf014Request getMnSapIf014Request(OrderSDO orderSDO) {
        MnSapIf014Request request = new MnSapIf014Request();
        request.setMessageHeader(RequestUtils.generateMessageHeader("MnSapIf014", "ECC"));

        //ext3字段需要传输创建人工号
        String creatorWorkId = "";
        BaselineGetEmployeeByIdsRequest baselineGetEmployeeByIdsRequest = new BaselineGetEmployeeByIdsRequest();
        baselineGetEmployeeByIdsRequest.setEmployeeIdList(Lists.newArrayList(orderSDO.getCreatorId()));
        Result<List<EmployeeSDO>> employee = baseDataService.baselineGetEmployeeByIds(baselineGetEmployeeByIdsRequest);
        if (Objects.nonNull(employee) && CollectionUtils.isNotEmpty(employee.getResult())) {
            EmployeeSDO employeeSDO = employee.getResult().get(0);
            creatorWorkId = employeeSDO.getWorkId();
        }
        String finalCreatorWorkId = creatorWorkId;

        //ext4子单需要传输赠品的主赠品行 同一个主单对应的赠品 需要根据单位和禁用标识分组 将最小行号赋值给组内其他赠品行
        Map<String, List<OrderLineSDO>> giftGroupMap = new HashMap<>();
        orderSDO.getOrderLineSDOS().stream().forEach(orderLineSDO -> {
            if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
                String mainLineNo = orderLineSDO.getFeatures().get("giftsMainSingle");
                String giftDisable = orderLineSDO.getFeatures().getOrDefault("giftDisable", "true");
                if (StringUtils.isNotBlank(mainLineNo) && "false".equals(giftDisable)) {
                    List<OrderLineSDO> orDefault = giftGroupMap.getOrDefault(mainLineNo, new ArrayList<>());
                    orDefault.add(orderLineSDO);
                    giftGroupMap.put(mainLineNo, orDefault);
                }
            }
        });
        if (MapUtils.isNotEmpty(giftGroupMap)) {
            for (Map.Entry<String, List<OrderLineSDO>> entry : giftGroupMap.entrySet()) {
                List<OrderLineSDO> value = entry.getValue();
                Map<String, List<OrderLineSDO>> unitGroupMap = value.stream().collect(Collectors.groupingBy(o -> o.getScItemSDO().getSaleUnit()));
                if (MapUtils.isNotEmpty(unitGroupMap)) {
                    for (Map.Entry<String, List<OrderLineSDO>> sameUnitGroup : unitGroupMap.entrySet()) {
                        List<OrderLineSDO> sameUnitGroupValue = sameUnitGroup.getValue();
                        if (sameUnitGroupValue.size() > 1) {
                            int firstGiftSerialNum = sameUnitGroupValue.stream().map(o -> Integer.parseInt(o.getSerialNumber())).sorted().findFirst().orElse(11);
                            sameUnitGroupValue.stream().filter(orderLineSDO -> Integer.parseInt(orderLineSDO.getSerialNumber()) > firstGiftSerialNum).forEach(o -> {
                                Map<String, String> features = o.getFeatures();
                                if (MapUtils.isNotEmpty(features)) {
                                    features.put("relationGiftSN", String.valueOf(firstGiftSerialNum));
                                }
                            });
                        }
                    }
                }


            }

        }

        List<MnSapIf014SDO> mnSapIf014DetailList = orderSDO.getOrderLineSDOS()
                .stream()
                .filter(orderLineSDO -> !OrderStatus.CANCELLED.getCode().equals(orderLineSDO.getStatus()))
                .map(orderLineSDO -> {
            MnSapIf014SDO sdo = new MnSapIf014SDO();

            //todo 赠品和特价活动的信息未传值 底嘉麟
            sdo.setGiftFlag("X");
            Map<String, String> features = orderLineSDO.getFeatures();
            List<ActivitySDO> activitySDOS = new ArrayList<>();
            if (Objects.nonNull(orderLineSDO.getFeatures()) && Objects.nonNull(features.get("activityDteails"))) {
                activitySDOS = JSONObject.parseArray(features.get("activityDteails"), ActivitySDO.class);
            }
            if (MapUtils.isNotEmpty(features) && features.get("giftFlag") != null && "gift".equals(features.get("giftFlag"))) {
                sdo.setGiftFlag(null);
            }

            //进行活动标识的拦截
            List<ActivitySDO> collect = activitySDOS.stream().filter(ActivitySDO::getIsSelect).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(collect)) {
                collect.stream().forEach(activitySDO -> {
                    if (ActivityTypeEnum.SPECIAL_OFFER_PRICE.getValue().equals(activitySDO.getActivityType())) {
                        sdo.setSpecialActivityId(activitySDO.getActivityCode());
                        sdo.setSpecialPromotionId(activitySDO.getActivityTermid());
                        if (activitySDO.getSpecialOfferPrice() != null) {
                            sdo.setActivityPrice(String.valueOf(activitySDO.getSpecialOfferPrice() / 100));
                        }
//                    if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
//                        sdo.setManualPromotionId(orderLineSDO.getFeatures().get("activityNumber"));
//                    }
//                    sdo.setGiftFlag(null);
                    }
                    if (ActivityTypeEnum.TAKE_GIFT.getValue().equals(activitySDO.getActivityType())) {
                        sdo.setGiftActivityId(activitySDO.getActivityCode());
                        sdo.setGiftPromotionId(activitySDO.getActivityTermid());
//                    if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
//                        sdo.setManualPromotionId(orderLineSDO.getFeatures().get("activityNumber"));
//                    }
                    }
                    if (ActivityTypeEnum.BUY_GIFT.getValue().equals(activitySDO.getActivityType())) {
                        sdo.setGiftActivityId(activitySDO.getActivityCode());
                        sdo.setGiftPromotionId(activitySDO.getActivityTermid());
//                    if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
//                        sdo.setManualPromotionId(orderLineSDO.getFeatures().get("activityNumber"));
//                    }
                    }
                    if (ActivityTypeEnum.REPLENISHMENT.getValue().equals(activitySDO.getActivityType())) {
                        sdo.setActivityId(activitySDO.getActivityCode());
                        sdo.setManualPromotionId(activitySDO.getActivityTermid());
//                    sdo.setGiftFlag(null);
                    }
                });
            }

            //2022.10.19 推送主键id给sap sap: 1开头 中间补0  总长度10
            sdo.setTradeOrderId(CodeUtil.convertSapTradeOrderId(orderSDO.getId()));
//            sdo.setTradeOrderId(orderSDO.getId());
            sdo.setOrderType(orderSDO.getOrderType());

            //平台销售组织->sap
            BaselineGetOrganizationByIdsRequest organizationByIdsRequest = new BaselineGetOrganizationByIdsRequest();
            List<String> saleIds = new ArrayList<>();
            saleIds.add(orderSDO.getOrganizationCode());
            saleIds.add(orderSDO.getDepartmentCode());
            saleIds.add(orderSDO.getSaleChannelCode());
            organizationByIdsRequest.setIds(saleIds);
            Map saleMap = (Map) baseDataService.baselineGetOrganizationByIds(organizationByIdsRequest);
            JSONArray result = JSONObject.parseObject(JSONObject.toJSONString(saleMap)).getJSONArray("result");
            if (CollectionUtils.isNotEmpty(result)) {
                for (int i = 0; i < result.size(); i++) {
                    JSONObject organizationSDO = result.getJSONObject(i).getJSONObject("organizationSDO");
                    String orgId = organizationSDO.getString("id");
                    if (orgId.equals(orderSDO.getOrganizationCode())) {
                        sdo.setSaleOrganizationCode(organizationSDO.getString("outCode"));
                    }
                    if (orgId.equals(orderSDO.getDepartmentCode())) {
                        sdo.setSaleGroup(organizationSDO.getString("outCode"));
                    }
                    if (orgId.equals(orderSDO.getSaleChannelCode())) {
                        sdo.setSaleDepartmentCode(organizationSDO.getString("outCode"));
                    }
                }
            }

            //平台发货仓->sap工厂和库存地点
            //判断下如果是换货订单 换货行用wareHouseCode的, 退货行用receiveWareHouseCode
            JSONArray cargoJsonArray = null;
            if (SaleOrderTag.EXCHANGE_ORDER.getCode().equals(orderSDO.getOrderType())) {
                if (EXCHANGE.equals(orderLineSDO.getOrderLineTag())){
                    cargoJsonArray = queryWareHouse(orderSDO.getWareHouseCode());
                }else if (RETURN.equals(orderLineSDO.getOrderLineTag())){
                    cargoJsonArray = queryWareHouse(orderSDO.getReceiveWareHouseCode());
                }
            }else {
                cargoJsonArray = queryWareHouse(orderSDO.getWareHouseCode());
            }
            log.info("getMnSapIf014Request cargoJsonArray={}", JSON.toJSONString(cargoJsonArray));
//            QueryCargoZoneByIdRequest zoneByIdRequest = new QueryCargoZoneByIdRequest();
//            List<String> cargoZoneIds = new ArrayList<>();
//            cargoZoneIds.add(orderSDO.getWareHouseCode());
//            zoneByIdRequest.setCargoZoneIdList(cargoZoneIds);
//            QueryCargoZoneByIdResponse queryCargoZoneByIdResponse = crUnifiedInventoryService.queryCargoZoneById(zoneByIdRequest);
//            JSONArray cargoJsonArray = JSONObject.parseObject(JSONObject.toJSONString(queryCargoZoneByIdResponse)).getJSONArray("result");
            if (CollectionUtils.isNotEmpty(cargoJsonArray)) {
                sdo.setDeliveryFactoryCode(cargoJsonArray.getJSONObject(0).getString("sapFactoryCode"));
                sdo.setDeliveryInventoryCode(cargoJsonArray.getJSONObject(0).getString("warehouseCode"));
            }

            //平台渠道->sap
            BaselineQueryChannelByPageRequest channelByPageRequest = new BaselineQueryChannelByPageRequest();
            channelByPageRequest.setChannelCode(orderSDO.getChannelCode());
            Map map = (Map) baseDataService.baselineQueryChannelByPage(channelByPageRequest);
            JSONObject jsonMap = JSONObject.parseObject(JSONObject.toJSONString(map));
            JSONArray jsonArray = jsonMap.getJSONObject("result").getJSONArray("content");
            if (CollectionUtils.isNotEmpty(jsonArray)) {
                JSONObject jsonObject1 = jsonArray.getJSONObject(0);
                sdo.setSapChannel(jsonObject1.getString("outCode"));
            }
            //todo 平台货品组->sap
            /*QueryScItemGroupRequest scItemGroupRequest = new QueryScItemGroupRequest();
            List<String> idList = new ArrayList<>();
            idList.add(orderSDO.getProductGroupCode());
            scItemGroupRequest.setIdList(idList);
            PageQueryScItemGroupListResponse scItemGroupListResponse = doHandler$queryScItemGroup(scItemGroupRequest);
            if (CollectionUtils.isNotEmpty(scItemGroupListResponse.getResult())) {
                JSONArray scItemGroups = JSONObject.parseArray(JSONObject.toJSONString(scItemGroupListResponse.getResult()));
                sdo.setProductGroupCode(scItemGroups.getJSONObject(0).getString("code"));
            }*/
            sdo.setProductGroupCode(orderSDO.getProductGroupCode());
            sdo.setCreator(orderSDO.getCreatorName());
            if (orderSDO.getGmtCreate() != null) {
                sdo.setCreateTime(DateFormatUtils.format(orderSDO.getGmtCreate(), "yyyy-MM-dd HH:mm:ss"));
                sdo.setDocTime(DateFormatUtils.format(orderSDO.getGmtCreate(), "yyyy-MM-dd"));
            }
            sdo.setSoldPartCode(orderSDO.getCustomerCode());
            sdo.setDeliveryPartCode(orderSDO.getReceiveAddressCode());
            sdo.setDeliveryPartName(orderSDO.getReceiveDetailAddress());
            if (orderSDO.getCustomerExpectDate() != null) {
                sdo.setExpectedDeliveryTime(DateFormatUtils.format(orderSDO.getCustomerExpectDate(), "yyyy-MM-dd"));
            }
            sdo.setShipType(orderSDO.getTransportModeCode());
            sdo.setCashCustomerName(orderSDO.getCashCustomerName());
            sdo.setCostCenter(orderSDO.getCostCenter());
            sdo.setOrderReason(orderSDO.getCreateReason());
            //sdo.setFeatures(orderSDO.getFeatureStr());
            sdo.setPurchaseNo(orderSDO.getCustomerReferenceNumber());
            //2023.4.20修改客户采购订单日期获取字段从 CustomerExpectDate(期望交货日期)改为新增的tCustomerPurchaseDate(客户采购订单日期字段)
            sdo.setPurchaseDate(orderSDO.getCustomerPurchaseDate()== null ? null: DateFormatUtils.format(orderSDO.getCustomerPurchaseDate(),"yyyy-MM-dd"));
            //sdo.setPurchaseDate(orderSDO.getCustomerExpectDate() == null ? null: DateFormatUtils.format(orderSDO.getCustomerExpectDate(),"yyyy-MM-dd"));
            sdo.setRemark(orderSDO.getRemark());
            sdo.setTradeOrderLineId(orderLineSDO.getSerialNumber());

            //平台货品->sap
//            BaselineQueryScItemByPageFromDbRequest scItemByPageRequest = new BaselineQueryScItemByPageFromDbRequest();
//            List<String> ids = new ArrayList<>();
//            ids.add(orderLineSDO.getScItemSDO().getScItemId());
//            scItemByPageRequest.setIdList(ids);
//            Map scItemMap = (Map)baseDataService.baselineQueryScItemByPageFromDb(scItemByPageRequest);
//            JSONArray scItemArray = JSONObject.parseObject(JSONObject.toJSONString(scItemMap)).getJSONObject("result").getJSONObject("result").getJSONArray("searchResult");
//            if (CollectionUtils.isNotEmpty(scItemArray)) {
//                sdo.setScItemId(scItemArray.getJSONObject(0).getString("outerId"));
//            }
            SearchScItemByDBWhenDegradedRequest scItemByPageRequest = new SearchScItemByDBWhenDegradedRequest();
            Map searchReqDTO = new HashMap();
            searchReqDTO.put("scItemIds", Lists.newArrayList(orderLineSDO.getScItemSDO().getScItemId()));
            scItemByPageRequest.setSearchReqDTO(searchReqDTO);
            Result<List<ScItemSDO>> scItemResult = baseDataService.searchScItemByDBWhenDegraded(scItemByPageRequest);
            if (scItemResult != null && CollectionUtils.isNotEmpty(scItemResult.getResult())) {
                sdo.setScItemId(scItemResult.getResult().get(0).getOuterId());
            }

            sdo.setQuantity(orderLineSDO.getScItemSDO().getQuantity().toString());
            //todo  销售单位先硬编码 之后再改
            sdo.setSaleUnit(orderLineSDO.getScItemSDO().getSaleUnit());
            sdo.setBaseUint(orderLineSDO.getScItemSDO().getInventoryUnitCode());
            sdo.setReturnFlag(orderLineSDO.getReturnCharacter());

            Long unitPrice = orderLineSDO.getScItemSDO().getUnitPrice();
            if (unitPrice != null) {
                sdo.setPrice(PriceConvertUnit.convertToYuan(unitPrice.toString()));
            }

            if (Objects.nonNull(orderLineSDO.getScItemSDO().getProductationTime())){
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
                String productionTime = null;
                try {
                    productionTime = simpleDateFormat.format(orderLineSDO.getScItemSDO().getProductationTime());
                    sdo.setExt5(productionTime);
                } catch (Exception e) {
                log.error("sap 014 v2 parse dom date error,",e);                }
            }

            //现金订单和退货订单  price字段给手工总金额
            if (StringUtils.isNotBlank(orderSDO.getOrderType())) {
                if (SaleOrderTag.CASH_ORDER.getCode().equals(orderSDO.getOrderType()) || SaleOrderTag.STD_RETURN_ORDER.getCode().equals(orderSDO.getOrderType())) {
                    if (MapUtils.isNotEmpty(orderLineSDO.getFeatures()) && StringUtils.isNotBlank(orderLineSDO.getFeatures().get(SaleOrderConstants.MANUAL_TOTAL_AMOUNT))) {
                        sdo.setPrice(PriceConvertUnit.convertToYuan(orderLineSDO.getFeatures().get(SaleOrderConstants.MANUAL_TOTAL_AMOUNT)));
                    }
                }
            }

            Long activityPrice = orderLineSDO.getScItemSDO().getActivityPrice();
            if (activityPrice != null) {
                sdo.setActivityPrice(PriceConvertUnit.convertToYuan(activityPrice.toString()));
            }

            sdo.setRemark(orderLineSDO.getRemark());
            sdo.setCostCenter(orderSDO.getCostCenter());
            sdo.setOrderReason(orderSDO.getCreateReason());

            sdo.setExt3(finalCreatorWorkId);
//            if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
//                sdo.setFeatures(JSONObject.toJSONString(orderLineSDO.getFeatures()));
//            }


            if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
                //买品行号
                sdo.setExt(orderLineSDO.getFeatures().get("giftsMainSingle"));
                //主赠品行号
                sdo.setExt4(orderLineSDO.getFeatures().get("relationGiftSN"));
            }

            if ("return".equals(orderLineSDO.getOrderLineTag()) && orderSDO.getOrderType().equals(SaleOrderTag.EXCHANGE_ORDER.getCode())) {
                sdo.setReturnFlag("1");
            }

            //add by 皓晖 at 20211217 for 014接口使用预留字段ext2下发我们订单抬头备注字段begin
            sdo.setExt2(orderSDO.getRemark());
            //add by 皓晖 at 20211217 for 014接口使用预留字段ext2下发我们订单抬头备注字段end

                    //F-B-b 场景，使用扩展字段中的过账仓信息123
                    if("300".equals(orderSDO.getOrderCategoryCode())){
                        Map<String, String> orderSDOFeatures = orderSDO.getFeatures();
                        //过账仓编码
                        String shippingWarehouseCode = orderSDOFeatures.get("shippingWarehouseCode");
                        //工厂仓编码
                        String deliveryFactoryCode = orderSDOFeatures.get("deliveryFactoryCode");
                        if(StringUtils.isNotBlank(deliveryFactoryCode)){
                            sdo.setDeliveryFactoryCode(deliveryFactoryCode);
                        }
                        //库存地点
                        String stockCode= orderSDOFeatures.get("stockCode");
                        if(StringUtils.isNotBlank(stockCode)){
                            sdo.setDeliveryInventoryCode(stockCode);
                        }
                    }
            if("ZRE3".equals(sdo.getOrderType())){
                sdo.setPrice(null);
            }
            return sdo;
        }).collect(Collectors.toList());

        request.setData(mnSapIf014DetailList);
        return request;
    }

    /**
     * 价格转换 ,这里临时使用 10000，为了是把数据推送下去。
     *
     * @param price
     * @return
     */
    private String priceConvert(String price) {
        BigDecimal tmpValue = new BigDecimal(price);
        String tmpPrice = tmpValue.divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_DOWN).toString();
        return tmpPrice;
    }

    /**
     * 根据逻辑仓库id查询仓库信息
     * @param wareHouseCode
     * @return
     */
    private JSONArray queryWareHouse(String wareHouseCode){
        QueryCargoZoneByIdRequest zoneByIdRequest = new QueryCargoZoneByIdRequest();
        List<String> cargoZoneIds = new ArrayList<>();
        cargoZoneIds.add(wareHouseCode);
        zoneByIdRequest.setCargoZoneIdList(cargoZoneIds);
        QueryCargoZoneByIdResponse queryCargoZoneByIdResponse = crUnifiedInventoryService.queryCargoZoneById(zoneByIdRequest);
        log.info("MnSapIf014V2ServiceImpl queryWareHouse queryCargoZoneByIdResponse={},zoneByIdRequest={}",JSON.toJSONString(queryCargoZoneByIdResponse),JSON.toJSONString(zoneByIdRequest));
        JSONArray cargoJsonArray = JSONObject.parseObject(JSONObject.toJSONString(queryCargoZoneByIdResponse)).getJSONArray("result");
        return cargoJsonArray;
    }
}
